<?
    class PrincipioLab_Date extends DateTime
    {
        const MONTH_JANUARY = 1;
        const MONTH_FEBRUARY = 2;
        const MONTH_MARCH = 3;
        const MONTH_APRIL = 4;
        const MONTH_MAY = 5;
        const MONTH_JUNE = 6;
        const MONTH_JULY = 7;
        const MONTH_AUGUST = 8;
        const MONTH_SEPTEMBER = 9;
        const MONTH_OCTOBER = 10;
        const MONTH_NOVEMBER = 11;
        const MONTH_DECEMBER = 12;


        public static $MONTHS_RUSSIAN = array(
            self::MONTH_JANUARY => "январь",
            self::MONTH_FEBRUARY => "февраль",
            self::MONTH_MARCH => "март",
            self::MONTH_APRIL => "апрель",
            self::MONTH_MAY => "май",
            self::MONTH_JUNE => "июнь",
            self::MONTH_JULY => "июль",
            self::MONTH_AUGUST => "август",
            self::MONTH_SEPTEMBER => "сентябрь",
            self::MONTH_OCTOBER => "октябрь",
            self::MONTH_NOVEMBER => "ноябрь",
            self::MONTH_DECEMBER => "декабрь"
        );


        public static $MONTHS_DECLENSION_RUSSIAN = array(
            self::MONTH_JANUARY => "января",
            self::MONTH_FEBRUARY => "февраля",
            self::MONTH_MARCH => "марта",
            self::MONTH_APRIL => "апреля",
            self::MONTH_MAY => "мая",
            self::MONTH_JUNE => "июня",
            self::MONTH_JULY => "июля",
            self::MONTH_AUGUST => "августа",
            self::MONTH_SEPTEMBER => "сентября",
            self::MONTH_OCTOBER => "октября",
            self::MONTH_NOVEMBER => "ноября",
            self::MONTH_DECEMBER => "декабря"
        );


        private $date_time_current;
        private $date_time;

        const DATETIME_BLANK = "1980-01-01 00:00:00";
        const DATETIME_NOW = "now";

        public function __construct($datetime = self::DATETIME_BLANK)
        {
            parent::__construct();

            $this->date_time_current = new DateTime("now");
            $this->setDateTime($datetime);
        }


        public function getDateTime() { return $this->date_time; }

        private function _setDateTime(DateTime $date_time)
        {
            $this->date_time = $date_time;
            return $this;
        }


        public function setDateTime($obj)
        {
            if ($obj instanceof DateTime)
                return $this->_setDateTime($obj);
            elseif ($obj instanceof PrincipioLab_Date)
                return $this->_setDateTime($obj->getDateTime());
            elseif ($obj == "")
                return $this->_setDateTime(new DateTime(self::DATETIME_BLANK));
            else
                return $this->_setDateTime(new DateTime($obj));
        }

        public function setDateTimeNow() { return $this->setDateTime(self::DATETIME_NOW); }
        public function setDateTimeBlank() { return $this->setDateTime(self::DATETIME_BLANK); }


        public function isBlank() { return ($this->toSQLFormat() == self::DATETIME_BLANK); }


        public function diff($object, $absolute = null) { return $this->getDateTime()->diff($object, $absolute); }

        public function getTimestamp() { return $this->getDateTime()->getTimestamp(); }
        public function getOffset() { return $this->getDateTime()->getOffset(); }
        public function getTimezone() { return $this->getDateTime()->getTimezone(); }
        public function format($format) { return $this->getDateTime()->format($format); }

        public function getYear() { return intval($this->getDateTime()->format("Y")); }
        public function getMonth() { return intval($this->getDateTime()->format("m")); }
        public function getDay() { return intval($this->getDateTime()->format("d")); }
        public function getHour() { return intval($this->getDateTime()->format("H")); }
        public function getMinute() { return intval($this->getDateTime()->format("i")); }
        public function getSecond() { return intval($this->getDateTime()->format("s")); }
        public function getMicroSecond() { return intval($this->getDateTime()->format("u")); }


        public function toSQLFormat()
        {
            // YYYY-MM-DD HH:MM:SS
            return $this->getYear()."-".$this->getMonth()."-".$this->getDay()." ".$this->getHour().":".$this->getMinute().":".$this->getSecond();
        }


        public function toHumanDeclension()
        {
            return add_zero($this->getDay())." ".(self::$MONTHS_DECLENSION_RUSSIAN[intval($this->getMonth())])." ".$this->getYear()."&nbsp;&nbsp;&nbsp;".add_zero($this->getHour()).":".add_zero($this->getMinute()).":".add_zero($this->getSecond());
        }


        public function diffWithNow($absolute = true)
        {
            $date_now = new DateTime("now");
            $date_interval = $date_now->diff($this->getDateTime(), $absolute);

            return (($date_interval->invert == "+") ? intval($date_interval->days) : intval($date_interval->days*(-1)));
        }


        public function diffToTimestamp(DateTime $date_time) { return self::doDiffToTimestamp($this, $date_time); }
        public function diffToTime(DateTime $date_time) { return self::doDiffToTime($this, $date_time); }


        public static function makeTimeFromTimestamp($timestamp)
        {
            $hours = floor($timestamp / 3600);
            $minutes = floor(($timestamp % 3600) / 60);
            $seconds = floor($timestamp - ($hours * 3600) - ($minutes * 60));

            return add_zero($hours).":".add_zero($minutes).":".add_zero($seconds);
        }


        public static function doDiffToTimestamp(DateTime $date_time_1, DateTime $date_time_2)
        {
            return ($date_time_1->getTimestamp() - $date_time_2->getTimestamp());
        }


        public static function doDiffToTime(DateTime $date_time_1, DateTime $date_time_2)
        {
            return Date::makeTimeFromTimestamp(Date::doDiffToTimestamp($date_time_1, $date_time_2));
        }


        public static function getNow() { return new Date(self::DATETIME_NOW); }
    }
?>